package com.qd.panda.service.stroke.order;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cdqidi.excel.ExcelExport;
import com.cdqidi.excel.util.ExportPage;
import com.cdqidi.exception.ApiException;
import com.cdqidi.util.DateUtil;
import com.qd.common.panda.domain.entity.order.OrderStatisticsDTO;
import com.qd.common.panda.domain.entity.order.UserStrokeOrderDisplayDTO;
import com.qd.common.panda.domain.entity.order.UserStrokeOrderQueryDTO;
import com.qd.panda.gas.station.req.BalanceReqDTO;
import com.qd.panda.gas.station.shell.last.LastShellHttpServiceImpl;
import com.qd.panda.service.stroke.BigDecimalUtil;
import com.qd.panda.service.stroke.DisplayUtil;
import com.qd.system.service.dict.MbUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
import java.util.Optional;

/**
 * 〈一句话功能简述〉<br>
 *
 * @author sjk
 * @create 2022-10-28 11:48
 * @since 1.0.0
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class UserOrderHolderService {

    private final UserStrokeOrderService userStrokeOrderService;
    private final UserStrokeOrderRefundService userStrokeOrderRefundService;
    private final LastShellHttpServiceImpl shellHttpServiceImpl;

    private final HttpServletResponse response;

    /**
     * 分页数据
     *
     * @param page 分页对象
     * @param dto  查询参数
     * @return 分页信息
     */
    @Transactional(readOnly = true)
    public IPage<UserStrokeOrderDisplayDTO> getOrderPage(Page<UserStrokeOrderDisplayDTO> page, UserStrokeOrderQueryDTO dto) {
        final QueryWrapper<UserStrokeOrderQueryDTO> queryWrapper = createQueryWrapper(dto);
        final IPage<UserStrokeOrderDisplayDTO> iPage = userStrokeOrderService.getBaseMapper().getOrderPage(page, queryWrapper, dto.getTripType());
        Optional.ofNullable(iPage.getRecords()).ifPresent(l -> l.forEach(this::buildDisplay));
        queryWrapper.clear();
        return iPage;
    }

    /**
     * 订单统计
     *
     * @param dto 查询参数
     * @return 订单统计值
     */
    @Transactional(readOnly = true)
    public OrderStatisticsDTO totalOrderStatistics(UserStrokeOrderQueryDTO dto) {
        final QueryWrapper<UserStrokeOrderQueryDTO> queryWrapper = createQueryWrapper(dto);
        OrderStatisticsDTO orderStatisticsDTO = userStrokeOrderService.getBaseMapper().totalOrderStatistics(queryWrapper, dto.getTripType());
        if (null == orderStatisticsDTO) {
            orderStatisticsDTO = new OrderStatisticsDTO();
        }
        if (null == orderStatisticsDTO.getQuantity()) {
            orderStatisticsDTO.setQuantity(0);
        }
        if (null == orderStatisticsDTO.getOrderAmount()) {
            orderStatisticsDTO.setOrderAmount(new BigDecimal(0));
        }
        if (null == orderStatisticsDTO.getPayAmount()) {
            orderStatisticsDTO.setPayAmount(new BigDecimal(0));
        }
        if (null == orderStatisticsDTO.getDiscountAmount()) {
            orderStatisticsDTO.setDiscountAmount(new BigDecimal(0));
        }
        queryWrapper.eq("t4.refund_status", DisplayUtil.REFUND_STATUS_1);
        OrderStatisticsDTO orderRefundStatisticsDTO = userStrokeOrderService.getBaseMapper().totalOrderRefundStatistics(queryWrapper, dto.getTripType());
        if (null == orderRefundStatisticsDTO) {
            orderStatisticsDTO.setRefundAmount(new BigDecimal(0));
            orderStatisticsDTO.setRefundQuantity(0);
        } else {
            orderStatisticsDTO.setRefundQuantity(Optional.ofNullable(orderRefundStatisticsDTO.getRefundQuantity()).orElse(0));
            orderStatisticsDTO.setRefundAmount(Optional.ofNullable(orderRefundStatisticsDTO.getRefundAmount()).orElse(new BigDecimal(0)));
        }
        orderStatisticsDTO.setOrderAmountDisplay(BigDecimalUtil.buildDefaultScale(orderStatisticsDTO.getOrderAmount()).stripTrailingZeros().toPlainString());
        orderStatisticsDTO.setPayAmountDisplay(BigDecimalUtil.buildDefaultScale(orderStatisticsDTO.getPayAmount()).stripTrailingZeros().toPlainString());
        orderStatisticsDTO.setDiscountAmountDisplay(BigDecimalUtil.buildDefaultScale(orderStatisticsDTO.getDiscountAmount()).stripTrailingZeros().toPlainString());
        orderStatisticsDTO.setRefundAmountDisplay(BigDecimalUtil.buildDefaultScale(orderStatisticsDTO.getRefundAmount()).stripTrailingZeros().toPlainString());
        //查询加油余额
        try {
            BalanceReqDTO base = new BalanceReqDTO();
            BigDecimal balance = shellHttpServiceImpl.balance(base);
            if (null != balance) {
                orderStatisticsDTO.setShellBalance(balance.stripTrailingZeros().toPlainString());
            }
        } catch (Exception e) {
            log.error("壳牌查询余额异常", e);
        }
        return orderStatisticsDTO;
    }

    /**
     * 导出Excel
     *
     * @param query 查询条件
     */
    @Transactional(readOnly = true)
    public void export(UserStrokeOrderQueryDTO query) {
        final ExportPage<UserStrokeOrderDisplayDTO, UserStrokeOrderDisplayDTO> exportPage = new ExportPage<>();
        try {
            final List<UserStrokeOrderDisplayDTO> list = exportPage.getAllForPage(page -> getOrderPage(page, query).getRecords());
            try {
                ExcelExport.downloadExcel(response, UserStrokeOrderDisplayDTO.class, () -> list);
            } catch (IOException e) {
                log.error("导出失败", e);
                throw new ApiException("导出失败");
            }
        } finally {
            exportPage.freeData();
        }
    }

    private QueryWrapper<UserStrokeOrderQueryDTO> createQueryWrapper(UserStrokeOrderQueryDTO dto) {
        final LocalDate now = LocalDate.now();
        final QueryWrapper<UserStrokeOrderQueryDTO> queryWrapper = new QueryWrapper<>();
        if (null != dto) {
            if (StringUtils.hasLength(dto.getBeginTime()) && DateUtil.strToLocalDate(dto.getBeginTime()).isAfter(now)) {
                throw new ApiException("开始时间不能大于当前时间");
            }
            if (StringUtils.hasLength(dto.getEndTime()) && DateUtil.strToLocalDate(dto.getEndTime()).isAfter(now)) {
                throw new ApiException("结束时间不能大于当前时间");
            }
            if (StringUtils.hasLength(dto.getBeginTime())) {
                queryWrapper.apply("date_format(t1.start_time,'%Y-%m-%d') >= {0}", dto.getBeginTime());
            }
            if (StringUtils.hasLength(dto.getEndTime())) {
                queryWrapper.apply("date_format(t1.start_time,'%Y-%m-%d') <= {0}", dto.getEndTime());
            }
            if (StringUtils.hasLength(dto.getParkId())) {
                queryWrapper.eq("t1.park_id", dto.getParkId());
            }
            if (StringUtils.hasLength(dto.getParkName())) {
                queryWrapper.like("t1.park_name", dto.getParkName());
            }
            if (StringUtils.hasLength(dto.getOrderId())) {
                queryWrapper.eq("t1.order_id", dto.getOrderId());
            }
            if (StringUtils.hasLength(dto.getPlateNumber())) {
                queryWrapper.eq("t1.plate_number", dto.getPlateNumber());
            }
            if (StringUtils.hasLength(dto.getUserId())) {
                queryWrapper.eq("t1.user_id", dto.getUserId());
            }
            if (StringUtils.hasLength(dto.getMobile())) {
                queryWrapper.eq("t2.mobile", dto.getMobile());
            }
            if (null != dto.getPayStatus()) {
                queryWrapper.eq("t1.pay_status", dto.getPayStatus());
            }
            if (null != dto.getTripType()) {
                queryWrapper.eq("t1.trip_type", dto.getTripType());
                if (dto.getTripType().equals(DisplayUtil.TRIP_TYPE_2)) {
                    if (StringUtils.hasLength(dto.getStationType())) {
                        queryWrapper.eq("t3.station_type", dto.getStationType());
                    }
                    if (StringUtils.hasLength(dto.getGasStationCompanyId())) {
                        Object[] gasStationCompanyIds = dto.getGasStationCompanyId().split(",");
                        queryWrapper.in("t3.gas_station_company_id",gasStationCompanyIds);
                    }
                }
            }
            if (StringUtils.hasLength(dto.getPromotionCode())) {
                queryWrapper.eq("t1.promotion_code", dto.getPromotionCode());
            }
        }
        queryWrapper.orderByDesc("t1.start_time");
        queryWrapper.orderByAsc("t1.park_id");
        queryWrapper.orderByDesc("t1.user_id");
        return queryWrapper;

    }

    private void buildDisplay(UserStrokeOrderDisplayDTO dto) {
        dto.setTripTypeDisplay(DisplayUtil.getTripTypeDisplay(dto.getTripType()));
        dto.setPayStatusDisplay(DisplayUtil.getPayStatusDisplay(dto.getPayStatus()));
        dto.setOrderAmountDisplay(Optional.ofNullable(dto.getOrderAmount()).map(amount -> BigDecimalUtil.buildDefaultScale(amount).stripTrailingZeros().toPlainString()).orElse(""));
        dto.setPayAmountDisplay(Optional.ofNullable(dto.getPayAmount()).map(amount -> BigDecimalUtil.buildDefaultScale(amount).stripTrailingZeros().toPlainString()).orElse(""));
        dto.setDiscountAmountDisplay(Optional.ofNullable(dto.getDiscountAmount()).map(amount -> BigDecimalUtil.buildDefaultScale(amount).stripTrailingZeros().toPlainString()).orElse(""));
        dto.setServiceChargeDisplay(Optional.ofNullable(dto.getServiceCharge()).map(amount -> BigDecimalUtil.buildDefaultScale(amount).stripTrailingZeros().toPlainString()).orElse(""));
        dto.setPromotionCodeDisplay(MbUtil.idToDisplay(dto.getPromotionCode()));
        if (null != dto.getStationType()) {
            dto.setStationTypeDisplay(MbUtil.idToDisplay(dto.getStationType()));
        }
        if (null != dto.getPayStatus() && dto.getPayStatus().equals(DisplayUtil.PAY_STATUS_1)) {
            //查询是否存在退款信息
            Optional.ofNullable(userStrokeOrderRefundService.refundAmountByOrderId(dto.getOrderId())).ifPresent(dto::setRefundAmount);
        }
//        if(dto.getTripType().equals(DisplayUtil.TRIP_TYPE_3)){
//            Optional.ofNullable(parkSpaceTenantService.getBaseMapper().spaceTenantById(dto.getOrderId())).ifPresent(orderSpaceTenantDTO -> {
//                ObjectNode objectNode = JacksonUtil.getObjectMapper().createObjectNode();
//                objectNode.put("spaceNumber",orderSpaceTenantDTO.getSpaceNumber());
//                objectNode.put("sysSpaceNumber",orderSpaceTenantDTO.getSysSpaceNumber());
//                dto.setParkInfo(objectNode);
//            });
//        }
    }

}